#include "CH552.H"
#include "Spi.h"
#undef SPI_Interrupt
#if SOFT_SPI

sbit SPI_SS = P1^4;
sbit SPI_MOSI = P1^5;
sbit SPI_MISO = P1^6;
sbit SPI_CLK = P1^7;

void SPI_Init(void) 
{
    P1_MOD_OC &=~ 0xB0;//|= 0xFF;
    P1_DIR_PU |= 0xB0;//|= 0xFF;                    //SCS,MOSI,SCK设推挽输出
    
    P1_MOD_OC &=~ 0X40;                              //MISO上拉输入
    P1_DIR_PU &=~ 0x40;//|= 0xFF;   
    SPI_SS = 1;
    SPI_MOSI = 0;
    SPI_MISO = 0;
    SPI_CLK = 0;
}

void SPI_W2Byte(UINT8 addr,UINT8 msByte,UINT8 lsByte)
{
    UINT8 ii = 0;
    UINT16 asmb = 0;
    SPI_SS = 0;
    //address finder
    for(ii=0;ii<8;ii++)
    {
        SPI_MOSI = addr&0x80;
        SPI_CLK = 1;
        addr<<=1;
        SPI_CLK = 0;
    }
    //give sometime to the slave
    asmb = (((UINT16)msByte)<<8) | lsByte;

    for(ii=0;ii<16;ii++)
    {
        SPI_MOSI = asmb&0x8000;
        SPI_CLK = 1;
        asmb<<=1;
        SPI_CLK = 0;
    }
    SPI_SS = 1;
}
#if 0
//通过取地址拿到两个字节,传参必须得有两个字节，否则可能传不出来
void SPI_R2Byte(UINT8 addr,UINT8* Byte2buf)
{
    UINT8 ii;
    UINT16 *dataBuf;
    SPI_SS = 0;
    addr|=0x80;
    for(ii=0;ii<8;ii++)
    {
        SPI_MOSI = addr &0x80;
        SPI_CLK = 1;
        addr<<=1;
        SPI_CLK = 0;
    }
    dataBuf = (UINT16 *)Byte2buf;
    for(ii=0;ii<16;ii++)
    {
        SPI_CLK = 1;
        (*dataBuf)<<=1;
        SPI_CLK = 0;
        *dataBuf |= SPI_MISO;
    }
    SPI_SS = 1;
}

/**/
void SPI_W1Byte(UINT8 addr,UINT8 dat)
{
    UINT8 ii = 0;
    SPI_SS = 0;
    //address finder
    for(ii=0;ii<8;ii++)
    {
        SPI_MOSI = addr&0x80;
        SPI_CLK = 1;
        addr<<=1;
        SPI_CLK = 0;
    }

    for(ii=0;ii<8;ii++)
    {
        SPI_MOSI = dat&0x80;
        SPI_CLK = 1;
        dat<<=1;
        SPI_CLK = 0;
    }

    SPI_SS = 0;
}

//通过取地址拿到1个字节,传参必须得有1个字节，否则可能传不出来
void SPI_R1Byte(UINT8 addr,UINT8* dat)
{
    UINT8 ii;
    SPI_SS = 0;
    addr|=0x80;
    for(ii=0;ii<8;ii++)
    {
        SPI_MOSI = addr &0x80;
        SPI_CLK = 1;
        addr<<=1;
        SPI_CLK = 0;
    }
    for(ii=0;ii<8;ii++)
    {
        SPI_CLK = 1;
        (*dat)<<=1;
        SPI_CLK = 0;
        *dat |= SPI_MISO;
    }
    SPI_SS = 0;
}
#endif
void SPI_MultStart(void)
{
    SPI_SS = 0;
}
void SPI_MultStop(void)
{
    SPI_SS = 1;
}
UINT8 SPI_MultRWByte(UINT8 dat)
{
    UINT8 Ret= 0;
    UINT8 ii;
    for(ii=0;ii<8;ii++)
    {
        
        SPI_MOSI = dat &0x80;
        SPI_CLK = 1;
        dat<<=1;
        Ret<<=1;
        SPI_CLK = 0;
        Ret |= SPI_MISO;
    }
    return Ret;
}
#else
/*******************************************************************************
* Function Name  : SPIMasterModeSet( UINT8 mode ) 
* Description    : SPI主机模式初始化
* Input          : UINT8 mode						 
* Output         : None
* Return         : None
*******************************************************************************/
void SPIMasterModeSet(UINT8 mode)
{
    SPI0_SETUP = 0;                                 //Master模式,高位在前
    if(mode == 0){
      SPI0_CTRL = 0x60;                             //模式0			
    }			
    else if(mode == 3){
      SPI0_CTRL = 0x68;                             //模式3
    }			
    P1_MOD_OC &=~ 0xB0;//|= 0xFF;
    P1_DIR_PU |= 0xB0;//|= 0xFF;                    //SCS,MOSI,SCK设推挽输出
    
    P1_MOD_OC |= 0X40;                              //MISO上拉输入
    P1_DIR_PU |= 0x40;//|= 0xFF;                
}

/*******************************************************************************
* Function Name  : CH552SPIInterruptInit()
* Description    : CH552SPI中断初始化
* Input          : None
* Output         : None
* Return         : None
*******************************************************************************/
void CH552SPIInterruptInit()
{
    //IP_EX |= bIP_SPI0;                                                       //SPI0中断优先级设置
    SPI0_SETUP |= bS0_IE_FIFO_OV | bS0_IE_BYTE;                                //使能接收1字节中断，使能FIFO溢出中断
    SPI0_CTRL |= bS0_AUTO_IF;                                                  //自动清S0_IF_BYTE中断标志
    SPI0_STAT |= 0xff;                                                         //清空SPI0中断标志
#ifdef SPI_Interrupt
    IE_SPI0 = 1;                                                               //使能SPI0中断
#endif
}

/*******************************************************************************
* Function Name  : CH552SPIMasterWrite(UINT8 dat)
* Description    : CH552硬件SPI写数据,主机模式
* Input          : UINT8 dat   数据
* Output         : None
* Return         : None
*******************************************************************************/
void CH552SPIMasterWrite(UINT8 dat)
{
    SPI0_DATA = dat;                                                           
    while(S0_FREE == 0);													   //等待传输完成		
//如果bS0_DATA_DIR为1，此处可以直接读取一个字节的数据用于快速读写	
}

/*******************************************************************************
* Function Name  : CH552SPIMasterRead( )
* Description    : CH552硬件SPI0读数据，主机模式
* Input          : None
* Output         : None
* Return         : UINT8 ret   
*******************************************************************************/
UINT8 CH552SPIMasterRead()
{
    SPI0_DATA = 0xff;
    while(S0_FREE == 0);
    return SPI0_DATA;
}

/*******************************************************************************
* Function Name  : SPISlvModeSet( ) 
* Description    : SPI从机模式初始化
* Input          : None						 
* Output         : None
* Return         : None
*******************************************************************************/
void SPISlvModeSet( )
{
    SPI0_SETUP = 0x80;                                                        //Slv模式,高位在前
    SPI0_CTRL = 0x89;                                                         //读写FIFO,自动清S0_IF_BYTE标志
    P1_MOD_OC &= 0x0F;
    P1_DIR_PU &= 0x0F;                                                        //SCS,MOSI,SCK,MISO全设置浮空输入
}

/*******************************************************************************
* Function Name  : CH552SPISlvWrite(UINT8 dat)
* Description    : CH552硬件SPI写数据，从机模式
* Input          : UINT8 dat   数据
* Output         : None
* Return         : None
*******************************************************************************/
void CH552SPISlvWrite(UINT8 dat)
{
    SPI0_DATA = dat;
    while(S0_FREE==0);		                                                     
}

/*******************************************************************************
* Function Name  : CH552SPISlvRead( )
* Description    : CH552硬件SPI0读数据，从机模式
* Input          : None
* Output         : None
* Return         : UINT8 ret   
*******************************************************************************/
UINT8 CH552SPISlvRead()
{
    while(S0_FREE == 0);
    return SPI0_DATA;
}

#if SPI_Interrupt
/*******************************************************************************
* Function Name  : SPIInterrupt(void)
* Description    : SPI 中断服务程序
*******************************************************************************/
void	SPIInterrupt( void ) interrupt INT_NO_SPI0 using 1                       //SPI中断服务程序,使用寄存器组1
{ 
}
#endif
#endif